/*
 * @(#)AtnaRepositoryService.java
 * Date 2014-01-18
 * Version 1.0
 * Author Jim Horner
 * Copyright (c)2012
 */


package us.hornerscorners.lamppost.repository.service;

import java.math.BigInteger;

import java.util.List;

import javax.enterprise.context.ApplicationScoped;

import javax.inject.Inject;

import ihe.iti.xds_b._2007.RetrieveDocumentSetResponseType;

import ihe.iti.xds_b._2007.RetrieveDocumentSetResponseType.DocumentResponse;

import oasis.names.tc.ebxml_regrep.xsd.rs._3.RegistryResponseType;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import us.hornerscorners.lamppost.atna.client.AtnaContext;
import us.hornerscorners.lamppost.atna.client.IAtnaClient;

import us.hornerscorners.lamppost.atna.client.utils.AtnaUtils;

import us.hornerscorners.lamppost.hl7v3common.utils.HL7Utils;

import us.hornerscorners.lamppost.model.audit.AuditContext;
import us.hornerscorners.lamppost.model.audit.AuditMessage;
import us.hornerscorners.lamppost.model.audit.EventIdentificationType;
import us.hornerscorners.lamppost.model.audit.ParticipantObjectIdentificationType;
import us.hornerscorners.lamppost.model.audit.TypeValuePairType;

import us.hornerscorners.lamppost.model.common.InstanceIdentifier;

import us.hornerscorners.lamppost.model.document.SubmissionSet;

import us.hornerscorners.lamppost.registry.constant.Metadata;
import us.hornerscorners.lamppost.registry.constant.ResponseStatus;


/**
 * Class description
 *
 *
 * @version        v1.0, 2014-01-18
 * @author         Jim Horner
 */
@ApplicationScoped
public class AtnaRepositoryService {

    /** Field description */
    @Inject
    private IAtnaClient atnaClient;

    /** Field description */
    private final Logger logger = LoggerFactory.getLogger(getClass());

    /**
     * Constructs ...
     *
     */
    public AtnaRepositoryService() {

        super();
    }

    /**
     * Method description
     *
     *
     * @param auditContext
     * @param subset
     * @param response
     */
    public void sendPersistReceivedAuditMessage(AuditContext auditContext,
            SubmissionSet subset, RegistryResponseType response) {

        if (this.atnaClient.isEnabled()) {

            try {

                AuditMessage msg = new AuditMessage();
                AtnaContext atnaContext = this.atnaClient.getAtnaContext();

                boolean success = false;

                if (response != null) {

                    success =
                        ResponseStatus.Success.getCode().equals(response.getStatus());
                }

                EventIdentificationType event = new EventIdentificationType();

                event.setEventID(AtnaUtils.createCodedValue("110107", "DCM", "Import"));
                event.setEventActionCode("C");
                event.setEventDateTime(AtnaUtils.createTimeStamp());
                event.setEventOutcomeIndicator(success
                                               ? BigInteger.ONE : BigInteger.ZERO);
                event.getEventTypeCode().add(auditContext.getEventType());
                msg.setEventIdentification(event);

                // Sender
                msg.getActiveParticipant().add(
                    AtnaUtils.createSourceParticipant(auditContext));

                // Receiver
                msg.getActiveParticipant().add(
                    AtnaUtils.createDestinationParticipant(atnaContext, auditContext));

                // Source
                msg.getAuditSourceIdentification().add(
                    AtnaUtils.createAuditSource(auditContext));

                if (subset != null) {

                    // Patient
                    InstanceIdentifier pid = subset.getPatientId();

                    if (pid != null) {

                        String pidcx = HL7Utils.toCXString(pid);

                        msg.getParticipantObjectIdentification().add(
                            AtnaUtils.createPatientIdentification(pidcx));
                    }

                    // Submission Set

                    ParticipantObjectIdentificationType ssobj =
                        new ParticipantObjectIdentificationType();

                    ssobj.setParticipantObjectTypeCode(Short.valueOf("2"));
                    ssobj.setParticipantObjectTypeCodeRole(Short.valueOf("20"));
                    ssobj.setParticipantObjectIDTypeCode(
                        AtnaUtils.createCodedValue(
                            Metadata.SubmissionSetClassificationNode.getURN(),
                            "IHE XDS Metadata", "submission set classificationNode"));
                    ssobj.setParticipantObjectID(subset.getUniqueId().getRoot());
                    msg.getParticipantObjectIdentification().add(ssobj);
                }

                this.atnaClient.sendAuditEvent(msg);

            } catch (Exception e) {

                logger.error("Exception sending ATNA", e);
            }
        }
    }

    /**
     * ITI 2b 3.43 Retrieve Document Set
     * Document Repository Audit Message
     *
     * @param auditContext
     * @param response
     */
    public void sendRetrieveReceivedAuditMessage(AuditContext auditContext,
            RetrieveDocumentSetResponseType response) {

        if (this.atnaClient.isEnabled()) {

            try {

                AuditMessage msg = new AuditMessage();
                AtnaContext atnaContext = this.atnaClient.getAtnaContext();

                boolean success = ResponseStatus.Success.getCode().equals(
                                      response.getRegistryResponse().getStatus());

                EventIdentificationType event = new EventIdentificationType();

                event.setEventID(AtnaUtils.createCodedValue("110106", "DCM", "Export"));
                event.setEventActionCode("R");
                event.setEventDateTime(AtnaUtils.createTimeStamp());
                event.setEventOutcomeIndicator(success
                                               ? BigInteger.ONE : BigInteger.ZERO);
                event.getEventTypeCode().add(auditContext.getEventType());
                msg.setEventIdentification(event);

                // Sender
                msg.getActiveParticipant().add(
                    AtnaUtils.createSourceParticipant(auditContext));

                // Receiver
                msg.getActiveParticipant().add(
                    AtnaUtils.createDestinationParticipant(atnaContext, auditContext));

                // Source
                msg.getAuditSourceIdentification().add(
                    AtnaUtils.createAuditSource(auditContext));

                List<DocumentResponse> docResponses = response.getDocumentResponse();

                if (docResponses.isEmpty() == false) {

                    for (DocumentResponse docResponse : docResponses) {

                        ParticipantObjectIdentificationType docObj =
                            new ParticipantObjectIdentificationType();

                        docObj.setParticipantObjectTypeCode(Short.valueOf("2"));
                        docObj.setParticipantObjectTypeCodeRole(Short.valueOf("3"));
                        docObj.setParticipantObjectIDTypeCode(
                            AtnaUtils.createCodedValue("9", "RFC-3881", "Report Number"));
                        docObj.setParticipantObjectID(docResponse.getDocumentUniqueId());

                        TypeValuePairType repId = new TypeValuePairType();

                        repId.setType("Repository Unique Id");
                        repId.setValue(docResponse.getDocumentUniqueId().getBytes());
                        docObj.getParticipantObjectDetail().add(repId);

                        TypeValuePairType homeId = new TypeValuePairType();

                        homeId.setType("ihe:homeCommunityID");
                        homeId.setValue(docResponse.getRepositoryUniqueId().getBytes());
                        docObj.getParticipantObjectDetail().add(homeId);
                    }
                }

                this.atnaClient.sendAuditEvent(msg);

            } catch (Exception e) {

                logger.error("Exception sending ATNA", e);
            }
        }
    }

    /**
     * ITI 2b 3.43 Retrieve Document Set
     * Document Consumer Audit Message
     *
     * @param auditContext
     * @param response
     */
    public void sendRetrieveRequestAuditMessage(AuditContext auditContext,
            RetrieveDocumentSetResponseType response) {

        if (this.atnaClient.isEnabled()) {

            try {

                AuditMessage msg = new AuditMessage();
                AtnaContext atnaContext = this.atnaClient.getAtnaContext();

                boolean success = ResponseStatus.Success.getCode().equals(
                                      response.getRegistryResponse().getStatus());

                EventIdentificationType event = new EventIdentificationType();

                event.setEventID(AtnaUtils.createCodedValue("110107", "DCM", "Import"));
                event.setEventActionCode("C");
                event.setEventDateTime(AtnaUtils.createTimeStamp());
                event.setEventOutcomeIndicator(success
                                               ? BigInteger.ONE : BigInteger.ZERO);
                event.getEventTypeCode().add(auditContext.getEventType());
                msg.setEventIdentification(event);

                // Sender
                msg.getActiveParticipant().add(
                    AtnaUtils.createClientSourceParticipant(atnaContext, auditContext));

                // Receiver
                msg.getActiveParticipant().add(
                    AtnaUtils.createClientDestinationParticipant(auditContext));

                // Source
                msg.getAuditSourceIdentification().add(
                    AtnaUtils.createAuditSource(auditContext));

                List<DocumentResponse> docResponses = response.getDocumentResponse();

                if (docResponses.isEmpty() == false) {

                    for (DocumentResponse docResponse : docResponses) {

                        ParticipantObjectIdentificationType docObj =
                            new ParticipantObjectIdentificationType();

                        docObj.setParticipantObjectTypeCode(Short.valueOf("2"));
                        docObj.setParticipantObjectTypeCodeRole(Short.valueOf("3"));
                        docObj.setParticipantObjectIDTypeCode(
                            AtnaUtils.createCodedValue("9", "RFC-3881", "Report Number"));
                        docObj.setParticipantObjectID(docResponse.getDocumentUniqueId());

                        TypeValuePairType repId = new TypeValuePairType();

                        repId.setType("Repository Unique Id");
                        repId.setValue(docResponse.getDocumentUniqueId().getBytes());
                        docObj.getParticipantObjectDetail().add(repId);

                        TypeValuePairType homeId = new TypeValuePairType();

                        homeId.setType("ihe:homeCommunityID");
                        homeId.setValue(docResponse.getRepositoryUniqueId().getBytes());
                        docObj.getParticipantObjectDetail().add(homeId);
                    }
                }

                this.atnaClient.sendAuditEvent(msg);

            } catch (Exception e) {

                logger.error("Exception sending ATNA", e);
            }
        }
    }
}
